home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Multimedia / Resource Library: Multimedia.iso / sgml / unix / sgmlc / sgmlmsg.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-03  |  12.2 KB  |  265 lines

  1. /******************************************************************************/
  2. /* Added PRNTSTAT routine for (verbose) printing of statistics structure. */
  3. /* Moved location processing here from SGMLIO. */
  4. /* New exiterr function for terminal errors.    (CODED 10/16/87)              */
  5. /******************************************************************************/
  6. #include "vmincl.h"           /* Include files for VM. */
  7. #include "vmxtrn.h"           /* Declarations for VM public variables. */
  8. /******************************************************************************/
  9. #define REALEOF '\032'        /* Ctl-Z is read as part of file in binary mode.*/
  10. #define FOPENRD "rb"          /* Binary not default: specify it. */
  11. #define MTRUNC 2              /* Truncate trailing CR/LF from msgs and parms. */
  12. /******************************************************************************/
  13. #define MAXARGLN FILESPEC     /* Maximum length of an argument in a msg. */
  14. #define MAXMSGLN  84          /* Max len of record in msgfile (with CR,LF). */
  15. /******************************************************************************/
  16. FILE *msgfp;                  /* "Handle" of msgfile (STREAM I/O). */
  17. long msgindx[MAXMSGS+1] ={0}; /* Offsets of messages in msgfile. */
  18. long spindex[MAXPCBS+MAXDCLS]={0};/* Offsets of special parameters in msgfile.*/
  19. UNCH locpref[] = "\n     ";   /* Location prefix (indent) for messages. */
  20. UNCH margpos[MAXARGS+1] = {0};/* Argument positions of current msg. */
  21. UNCH msgid[5] = {0};          /* Message class and 3 digit ID of msg. */
  22. UNCH msgpref[] = "\n        ";/* General prefix (indent) for messages. */
  23. UNCH outchar[2] = " ";        /* Current character, censored for printing. */
  24. UNCH sevcode[2] = {0};        /* Severity code of current msg. */
  25. UNCH *margv[MAXARGS+2] = {    /* Ptrs to argument strings (in pd). */
  26.      pd,                           /* Full message file record. */
  27.      pd+MAXMSGLN+1,                /* 1st parameter. */
  28.      pd+MAXMSGLN+1+   MAXARGLN+1,  /* 2nd parameter. */
  29.      pd+MAXMSGLN+1+2*(MAXARGLN+1)  /* Special parameter text (errsp). */
  30. };
  31. UNCH *hdrall = 0;             /* Initial header for all error messages. */
  32. UNCH *hdrdoc = 0;             /* Header for document markup error messages. */
  33. UNCH *hdrfil = 0;             /* Header for file access error messages. */
  34. UNCH *hdrloc = 0;             /* Header for entity location stack in messages.*/
  35. UNCH *hdrmd2 = 0;             /* Header for markup declaration messages. */
  36. UNCH *hdrmd3 = 0;             /* Header for markup dcl msg with subdcl. */
  37. UNCH *hdrtag = 0;             /* Header for tag stack list in messages. */
  38. UNCH **hdrs[MAXHDRS] = {      /* Headers of error messages. */
  39.      &hdrall, &hdrdoc, &hdrfil,
  40.      &hdrloc, &hdrmd2, &hdrmd3, &hdrtag
  41. };
  42. /******************************************************************************/
  43. /* SGMLMSG: Text processor message services for SGML.
  44.             Do not return to SGML if the error type is EXITERR.
  45. */
  46. VOID sgmlmsg(ie)
  47. struct ipberr *ie;            /* Ptr to error message control block. */
  48. {
  49.      UNCH *pt;                /* Error handling: ptr to message text. */
  50.      int margc;               /* Error handling: number of msg arguments. */
  51.      int i;                   /* Loop counter; work variable. */
  52.  
  53.      getscbs((struct source *)ie->sgmlscbs,       /* Get SCBs from SGML. */
  54.           ie->sgmles);
  55.      ++cnterr;                                    /* Increment msg counter. */
  56.      pt = getmsg(msgindx[ie->errnum]);            /* Get msg text and data. */
  57.      margc = *margpos=='0' ? 0 : (int)strlen(margpos); /* Get argument count. */
  58.      for (i = 0; ++i<=margc;) {                   /* Get args from SGML. */
  59.           margpos[i-1] -= '0';                    /* Convert to number. */
  60.           memcpy( margv[i] , ie->eparm[i-1], (UNS)MAXARGLN );
  61.           margv[i][MAXARGLN] = '\0';              /* Truncate for safety. */
  62.      }
  63.      printf("\n"); printf(hdrall, msgid, sevcode);
  64.      switch (ie->errtype) {
  65.      case MDERR:              /* Error in markup declaration. */
  66.           printf(" ");
  67.           printf(hdrmd3, getparm(ie->errsp), ie->subdcl, ie->parmno);
  68.           break;
  69.      case MDERR2:             /* Error in markup declaration: no subdcl. */
  70.           printf(" "); printf(hdrmd2, getparm(ie->errsp), ie->parmno);
  71.           break;
  72.      case DOCERR:             /* Error in document markup. */
  73.      case EXITERR:            /* Terminal error in document markup. */
  74.           outchar[0] = ZAPEOL(CC);                /* Censor CC for printing. */
  75.           printf(" "); printf(hdrdoc, getparm(ie->errsp), outchar, CC);
  76.           break;
  77.      case FILERR:             /* Error in file access. */
  78.           printf(" "); printf(hdrfil, curfile);
  79.           break;
  80.      }
  81.      if (tpsw.swenttr) {
  82.           i = tpes;
  83.           for (tpes = -1; ++tpes<i;) errloc(locpref, hdrloc);
  84.      }
  85.      errloc(locpref, hdrloc); printf(":");
  86.      if (eltrsw) {
  87.           printf(msgpref); printf(hdrtag);
  88.           for (i = -1; ++i<=tpts;) printf(" %s", &tptags[i][0]);
  89.      }
  90.      printf(msgpref); prtmsg(pt, margc);
  91.      if (ie->errtype==EXITERR) exit((int)ie->errnum);
  92.      else return;
  93. }
  94. /******************************************************************************/
  95. /* MSGINIT: Read msgfile and build index to error messages.
  96.             Errors of class "W" are clearly markup errors,
  97.             but the parser was able to continue normal processing.
  98.             All other errors require the parser to depart from normal
  99.             processing in the manner indicated in the error message.
  100. */
  101. VOID msginit()
  102. {
  103.      UNCH leadchar[2];        /* First nonblank character in msg record. */
  104.      long offset;             /* Offset of msg in file. */
  105.      int msgno;               /* Number of current msg. */
  106.  
  107.      if (!filefind(msgfptr, pd)) {     /* Search dir and path. */
  108.           printf(
  109. "\nVM007-> Unable to open %s message file; processing ended.",
  110.           msgfptr);
  111.           exit(007);
  112.      }
  113.      msgfp = fopen(pd, FOPENRD);
  114.  
  115.      /* Place offsets in message number array. */
  116.      for (offset = 0; fgets(pd, MAXMSGLN+1, msgfp) && *pd!=REALEOF;
  117.           offset = ftell(msgfp)) {
  118.           /* Skip blank lines and those with * as first nonblank. */
  119.           sscanf(pd, "%1s", leadchar);
  120.           if (*leadchar!='*' && *leadchar!='\0') {
  121.                /* Not a comment: save the offset in the msg number array. */
  122.                sscanf(pd, "%3d", &msgno);         /* Get message number. */
  123.                if (msgno<1) {
  124.                     if (umsginit(-msgno, offset)==0) continue;
  125.                }
  126.                else if (msgno<=MAXMSGS) {
  127.                     msgindx[msgno] = offset;/* Save offset of this message. */
  128.                     continue;
  129.                }
  130.                printf(
  131. "\nVM008-> Bad item %d in SGML.MSG at offset %ld; processing ended.",
  132.                msgno, offset);
  133.                exit(8);
  134.           }
  135.      }
  136.      fseek(msgfp, 0L, SEEK_SET);     /* I think this avoids a bug. */
  137. }
  138. /******************************************************************************/
  139. /* UMSGINIT: User exit from message file initialization to get
  140.              message header text strings, parameter strings, and
  141.              national-language-specific text strings from the msgfile.
  142. */
  143. int umsginit(msgno, offset)
  144. int msgno;                    /* Number of special msg as positive number. */
  145. long offset;                  /* Offset of special msg in file. */
  146. {
  147.           if (msgno<MAXHDRS) {    /* Special text is a message header. */
  148.                *hdrs[msgno] = savestr(getmsg(offset));
  149.                return 0;
  150.           }
  151.           if (msgno<MAXHDRS+MAXPCBS+MAXDCLS) {
  152.                spindex[msgno-MAXHDRS] = offset;
  153.                return 0;
  154.           }
  155.           return(-1);
  156. }
  157. /******************************************************************************/
  158. /* GETMSG: Find a specified msg record, parse it, and return ptr to text.
  159. */
  160. UNCH *getmsg(msgoff)
  161. long msgoff;                  /* Offset of message to be found and parsed. */
  162. {
  163.      UNCH *pt;                /* Ptr to current msg text. */
  164.  
  165.      fseek(msgfp, msgoff, SEEK_SET);
  166.      fgets(pd, MAXMSGLN+1, msgfp);
  167.      sscanf(pd, "%*d %1s %4s %3s", sevcode, msgid, margpos);
  168.      pt = strchr(pd, '%');         /* Find trigger at start of text. */
  169.      while (*++pt==' ') ;          /* Strip leading blanks from text. */
  170.      pt[strlen(pt)-MTRUNC] = '\0'; /* Strip trailing newline from text. */
  171.      return(pt);
  172. }
  173. /******************************************************************************/
  174. /* GETPARM: Find a specified parameter record, parse it, and return ptr to text.
  175. */
  176. UNCH *getparm(msgind)
  177. UNS msgind;                   /* Index of special parameter to be found. */
  178. {
  179.      UNCH *pt = margv[MAXARGS+1];  /* Ptr to special parameter text. */
  180.  
  181.      fseek(msgfp, spindex[msgind], SEEK_SET); /* Position file ptr to record. */
  182.      fgets(pt, MAXARGLN+1, msgfp); /* Copy record to special arg buffer. */
  183.      pt += 4;                      /* Find start of text. */
  184.      pt[strlen(pt)-MTRUNC] = '\0'; /* Strip trailing newline from text. */
  185.      return(pt);
  186. }
  187. /******************************************************************************/
  188. /* PRTMSG: Print the message with substituted arguments.
  189. */
  190. VOID prtmsg(pt, argc)
  191. UNCH *pt;                     /* Ptr to current msg text. */
  192. int argc;                     /* Number of arguments for this msg. */
  193. {
  194.      switch (argc) {
  195.           case 0:
  196.                printf(pt);
  197.                return;
  198.           case 1:
  199.                printf(pt, margv[margpos[0]]);
  200.                return;
  201.           case 2:
  202.                printf(pt, margv[margpos[0]], margv[margpos[1]]);
  203.                return;
  204.           case 3:
  205.                printf(pt, margv[margpos[0]], margv[margpos[1]],
  206.                           margv[margpos[2]]);
  207.                return;
  208.      }
  209. }
  210. /******************************************************************************/
  211. /* GETSCBS: Update the source control block stack by copying entries from SGML.
  212.             If there are new entries (i.e., entities have opened), copy all
  213.             entries from the previous current entry to the new current entry
  214.             and change the current level.
  215.             If there are fewer entries (i.e., entities have closed), change
  216.             the current level and copy its entry.
  217.             If the level has not changed (i.e., no entity activity, or an
  218.             equal number of opens and closes), just copy the current entry.
  219. */
  220. VOID getscbs(sgmlscbs, sgmles)
  221. PSCB sgmlscbs;                /* Ptr to SGML scb stack. */
  222. int sgmles;                   /* SGML scb stack level. */
  223. {
  224.      register int i;          /* Signed work variable. */
  225.      register UNS u;          /* Unsigned work variable. */
  226.  
  227.      if ((i = sgmles-tpes)>0) /* Entities have opened: copy all new entries. */
  228.           u = (i+1)*SCBSZ;    /* Size of scbs to copy (include last current). */
  229.      else {
  230.           if (i<0) tpes = sgmles; /* Entities have closed: new current level. */
  231.           u = SCBSZ;              /* Copy current level only. */
  232.      }
  233.      memcpy((UNIV)&tpscbs[tpes], (UNIV)&sgmlscbs[tpes], u);
  234.      if (i>0) tpes = sgmles;      /* New current level if entities opened. */
  235.      curfile = FLID+1;            /* Current file for use by SGMLMSG. */
  236. }
  237. /******************************************************************************/
  238. /* ERRLOC: Read tpscbs and print location information.
  239. */
  240. VOID errloc(pref, hdr)
  241. UNCH *pref, *hdr;
  242. {
  243.      printf(pref);
  244.      printf(hdr, RCNT, CCNT, ENTITY+1, (FILESW) ? FLID+1 : "*INTERNAL");
  245. }
  246. /******************************************************************************/
  247. /* LOCATION: Print location prefix for VM messages.
  248.              If the entity has changed since last time (possible even if
  249.              the stack level is the same), print the new entity information.
  250. */
  251. VOID location(num)
  252. int num;
  253. {
  254.      if (oldent!=ECBPTR) {    /* Print message if entity has changed. */
  255.           oldent = ECBPTR;
  256.           printf(
  257. "\nVM100-> Entity is %s in %s.",
  258.           ENTITY+1, (FILESW) ? FLID+1 : "*INTERNAL");
  259.      }
  260.      printf(
  261. "\nVM1%02d-> %03u %03d: ",
  262.      num, RCNT, CCNT);
  263. }
  264. /******************************************************************************/
  265.